use sea_orm::entity::prelude::*;
use sea_orm::ActiveValue::Set;
use serde_json::Value;
use chrono::{DateTime, Utc};
use crate::entities::policy::Policy;

#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
#[sea_orm(table_name = "policy_information")]
pub struct Model {
    #[sea_orm(primary_key)]
    pub policy_id: String,
    #[sea_orm(column_type = String(255))]
    pub policy_name: String,
    #[sea_orm(column_type = String(512))]
    pub policy_description: String,
    #[sea_orm(column_type = Text)]
    pub policy_content: String,
    pub is_default: bool,
    pub policy_version: i32,
    pub create_time: DateTime<Utc>,
    pub update_time: DateTime<Utc>,
    #[sea_orm(indexed, column_type = String(36))]
    pub user_id: String,
    #[sea_orm(column_type = Json)]
    pub attester_type: Value,
    #[sea_orm(column_type = Binary(512))]
    pub signature: Vec<u8>,
    pub valid_code: i8,
    #[sea_orm(column_type = String(36))]
    pub key_version: String,
    #[sea_orm(column_type = String(128))]
    pub product_name: String,
    #[sea_orm(column_type = String(128))]
    pub product_type: String,
    #[sea_orm(column_type = String(128))]
    pub board_type: String,
}

// Reserved enumeration for establishing table relationship
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}

impl Relation {
    // Directly panic when attempting to use associated table behavior
    pub fn related_entity() -> RelationDef {
        panic!("Associated table behavior not realized")
    }
}

// Implemented default behavior for entity's ActiveModel
impl ActiveModelBehavior for ActiveModel {}

impl From<Policy> for ActiveModel {
    fn from(policy: Policy) -> Self {
        let attester_type = serde_json::to_value(policy.attester_type)
            .unwrap_or(Value::Array(vec![]));

        ActiveModel {
            policy_id: Set(policy.id.to_string()),
            policy_name: Set(policy.name),
            policy_description: Set(policy.description),
            policy_content: Set(policy.content),
            is_default: Set(policy.is_default),
            policy_version: Set(policy.version as i32),
            // Here creation time equals update time
            create_time: Set(DateTime::<Utc>::from_timestamp(policy.update_time as i64, 0).unwrap_or_default()),
            update_time: Set(DateTime::<Utc>::from_timestamp(policy.update_time as i64, 0).unwrap_or_default()),
            user_id: Set(String::new()),
            attester_type: Set(attester_type),
            signature: Set(Vec::new()),
            valid_code: Set(0),
            key_version: Set(String::new()),
            product_name: Set(String::new()),
            product_type: Set(String::new()),
            board_type: Set(String::new()),
        }
    }
}